package com.init.framework.interceptor;
/**
 *
 **/

import com.alibaba.fastjson.JSONObject;
import com.init.common.constant.Constants;
import com.init.common.utils.StringUtils;
import com.init.common.utils.TokenUtils;
import com.init.framework.interceptor.annotation.PassToken;
import com.init.framework.interceptor.annotation.UserToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;

/**
 * @Author weiwei
 * @Date 2021-10-12 15:59
 * @description token校验
 **/
public class TokenInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
        String token = request.getHeader(Constants.TOKEN_HEARD);
        //如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        // 如果是pass注解直接通过
        Method method =( (HandlerMethod)(handler)).getMethod();
        if(method.isAnnotationPresent(PassToken.class) ) return true;
        JSONObject jsonObject = new JSONObject();
        response.setCharacterEncoding("UTF-8");
        //用户校验
        if(method.isAnnotationPresent(UserToken.class) ){
            return userCheck(request, response, token, jsonObject);
        }
        return true;
    }



    private boolean userCheck(HttpServletRequest request, HttpServletResponse response, String token, JSONObject jsonObject) throws IOException {
        if(tokenCheck(token, response, jsonObject)) return false;
        Long userId = TokenUtils.getUserId(request);
        if(userId == null){
            assembleResp(response, jsonObject, "无效token，请重新获取");
            return false;
        }

        //todo 查询数据库用户

        return redisCheck(Constants.USER_TOKEN_REDIS_KEY, response, token, jsonObject);
    }



    public boolean tokenCheck(String token, HttpServletResponse response, JSONObject jsonObject) throws IOException {
        PrintWriter out;
        if (StringUtils.isEmpty(token)) {
            assembleResp(response, jsonObject, "无效token，请重新获取");
            return true;
        }

        boolean r = TokenUtils.verifyToken(token);
        if (!r) {
            assembleResp(response, jsonObject, "无效token，请重新获取");
            return true;
        }
        return false;
    }


    public void assembleResp(HttpServletResponse response, JSONObject jsonObject, String s) throws IOException {
        assembleResp( 401 , response,  jsonObject,  s);
    }
    public void assembleResp(int code ,HttpServletResponse response, JSONObject jsonObject, String s) throws IOException {
        PrintWriter out;
        response.setStatus(200);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        jsonObject.put("code", code);
        jsonObject.put("message", s);
        out = response.getWriter();
        out.println(jsonObject);
    }

    public boolean redisCheck(String key,HttpServletResponse response, String token, JSONObject jsonObject) throws IOException {
        String redisToken = (String) redisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(redisToken) || !token.equals(redisToken)) {
            assembleResp(response, jsonObject, "无效token，请重新获取");
            return false;
        }
        return true;
    }
}
